package com.bjsxt.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

/**
 * 
 * 
 * @author michael
 * @date 2021/06/23
 * @version 1.0
 * @Copyright Copyright (c) 2021, michael.xie@adsnova.cn All Rights Reserved.
 */
@EnableAuthorizationServer // 开启授权服务器
@Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private PasswordEncoder passwordEncoder;  // 加密工具
    
    @Autowired
    private AuthenticationManager authenticationManager;  // 验证管理器
    
    
    @Autowired
    private UserDetailsService userDetailsService;
    
    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    /**
     * 添加第三方客户端
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        clients.inMemory() // 加载在内存中
            .withClient("coin-api") // 第三方客户端的名称
            .secret(passwordEncoder.encode("coin-secret")) // 第三方客户端的密钥
            .scopes("all") // 第三方客户端的授权范围
            .accessTokenValiditySeconds(3600) // 获取token的有效期
            .refreshTokenValiditySeconds(7 * 3600); // refresh token的有效期
        super.configure(clients);
    }

    /**
     * 验证管理器
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
                    .userDetailsService(userDetailsService)
                    // .tokenStore(redisTokenStore()); // 用redis来存储 token值(默认是基于内存存储的)
                    .tokenStore(jwtTokenStore()) // 用jwt来存储 token值(默认是基于内存存储的)
                    .tokenEnhancer(jwtAccessTokenConverter()); // 决定token怎么产生 用转化器
        super.configure(endpoints);
    }
    
    /**
     * 使用redis存储token
     */
    public TokenStore redisTokenStore() {
        return new RedisTokenStore(redisConnectionFactory);
    }
    
    /**
     * 使用jwt存储token（把用户信息放在token中 而不是需要用token在鉴权服务器中获取用户信息）
     */
    public TokenStore jwtTokenStore() {
        JwtTokenStore jwtTokenStore = new JwtTokenStore(jwtAccessTokenConverter());
        return jwtTokenStore;
    }
    
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        ClassPathResource classPathResource = new ClassPathResource("coinexchange.jks");
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(classPathResource, "coinexchange".toCharArray());
        jwtAccessTokenConverter.setKeyPair(keyStoreKeyFactory.getKeyPair("coinexchange", "coinexchange".toCharArray()));
        return jwtAccessTokenConverter;
    }
}
